package com.vf.cloud.paas.app.agent.common.server.signalling.util;

import java.util.HashMap;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.JsonKit;
import com.jfinal.kit.StrKit;
import com.vf.cloud.paas.app.agent.common.server.signalling.pool.PlayerPool;
import com.vf.cloud.paas.app.agent.common.server.signalling.pool.StreamerPool;
import com.vf.cloud.paas.common.cirrus.Cirrus;
import com.vf.cloud.paas.common.service.IRedis;
import com.vf.cloud.paas.common.util.PrefixUtil;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class SignallingUtil {

	public static void disconnectedPlayer(String asLongText) {
		String token = PlayerPool.getTokenByChannelId(asLongText);
		if (!StrKit.isBlank(token) && StreamerPool.containsToken(token)) {
			StreamerPool.killByToken(token);
		}
		PlayerPool.removeByChannelId(asLongText);
	}

	public static void sendPing(ChannelHandlerContext ctx, long currentTimeMillis) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "pong");
		clientConfig.put("time", currentTimeMillis);
		send(ctx, JsonKit.toJson(clientConfig));
	}

	public static void sendPong(ChannelHandlerContext ctx, long currentTimeMillis) {
		Map<String, Object> clientConfig = new HashMap<String, Object>();
		clientConfig.put("type", "pong");
		clientConfig.put("time", currentTimeMillis);
		send(ctx, JsonKit.toJson(clientConfig));
	}

	/**
	 * MessageToPlayer
	 * 
	 * @param playerId
	 * @param msg
	 */
	public static void sendMessageToPlayer(String playerId, JSONObject msg) {
		ChannelHandlerContext player = PlayerPool.getByToken(playerId);
		if (null == player) {
			log.info(String.format("dropped message {%s} as the player ${playerId} is not found", msg.getString("type"),
					playerId));
			return;
		}
		send(player, JsonKit.toJson(msg));
	}

	/**
	 * onStreamerDisconnected
	 * 
	 * @param asLongText
	 */
	public static void onStreamerDisconnected(String asLongText, IRedis redisImpl) {
		String token = StreamerPool.getTokenByChannelId(asLongText);
		StreamerPool.removeByChannelId(asLongText);
		log.error("Streamer disconnected，token:" + token);
		// GPU 管理
		if (!StrKit.isBlank(token) && redisImpl != null) {
			String GPUIndex = redisImpl.get(token);
			log.error("Streamer disconnected，GPUIndex:" + GPUIndex);
			if (!StrKit.isBlank(GPUIndex)) {
				Cirrus.renderClient.sendGpuInfo(GPUIndex,GPUIndex.replaceFirst(PrefixUtil.GPU_Free, PrefixUtil.GPU_Used));
				redisImpl.delete(GPUIndex);
			}
			disconnectAllPlayers(token);
		}
		log.error("Streamer disconnected，Concurrent_Streamer:" + Cirrus.Concurrent_Streamer.size());
	}

	/**
	 * disconnectAllPlayers
	 * 
	 * @param asLongText
	 */
	public static void disconnectAllPlayers(String token) {
		log.error("Streamer disconnected，disconnectAllPlayers" + token);
		PlayerPool.removeByToken(token);
		log.error("Streamer disconnected，disconnectAllPlayers" + token);
//		console.log("killing all players");RedisImpl
//		let clone = new Map(players);
//		for (let player of clone.values()) {
//			if (player.id != SFUPlayerId) { // dont dc the sfu
//				player.ws.close(code, reason);
//			}
//		}
	}

	public static void sendMessageToController(String playerId, JSONObject msg, boolean skipStreamer) {
		if (!skipStreamer) {
			ChannelHandlerContext streamer = StreamerPool.getByToken(playerId);
			if (streamer != null) {
				send(streamer, JsonKit.toJson(msg));
			}
		}
	}

	/**
	 * onPlayerDisconnected
	 * 
	 * @param asLongText
	 */
	public static void onPlayerDisconnected(String asLongText) {
		PlayerPool.removeByChannelId(asLongText);
		log.error("Player disconnected，Concurrent_Player:" + Cirrus.Concurrent_Player.size());
	}

	public static void send(ChannelHandlerContext ctx, String json) {
		if (ctx != null) {
			ctx.channel().writeAndFlush(new TextWebSocketFrame(json)).addListener(new ChannelFutureListener() {
				@Override
				public void operationComplete(ChannelFuture future) throws Exception {
					if (future.isSuccess()) {
						// log.info(String.format("-> Streamer:%s", json));
					} else {
						// log.info(String.format("-> Streamer isError :%s", json));
					}
				}
			});
		}
	}

//	public static void closePlayer(String token) {
//		StreamerPool.killByToken(token);
//	}

}
